本篇文章同步發表於 個人部落格 Jim's Blog
上一篇我們在後端建立了 Token 發行與驗證的機制,今天我們回到主題在 Blaoz 怎麼取得 Token
首先我們建立一個登入的頁面,有帳號和密碼欄位以及一個送出的按鈕
Blazor.JWT.Client
專案內的Page
資料夾建立Login.razor
,並且完成表單@page "/Login"
<div class="form-signin w-100 m-auto">
<form data-bitwarden-watching="1">
<h1 class="h3 mb-3 fw-normal">請登入</h1>
<div class="form-floating">
<input type="email" class="form-control" id="floatingInput" placeholder="name@example.com">
<label for="floatingInput">Email address</label>
</div>
<div class="form-floating">
<input type="password" class="form-control" id="floatingPassword" placeholder="Password">
<label for="floatingPassword">Password</label>
</div>
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> 記住我
</label>
</div>
<button class="w-100 btn btn-lg btn-primary" type="submit">登入</button>
<p class="mt-5 mb-3 text-muted">© 2022</p>
</form>
</div>
@code {
}
.form-signin {
max-width: 330px;
padding: 15px;
}
.form-signin .form-floating:focus-within {
z-index: 2;
}
.form-signin input[type="email"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
main {
display: flex;
align-items: center;
padding-top: 40px;
padding-bottom: 40px;
background-color: #f5f5f5;
}
Blazor.Jwt.Shared
建立登入表單所需要的類別LoginDto.cs
public class LoginDto
{
/// <summary>
/// 使用者名稱
/// </summary>
public string Username { get; set; }
/// <summary>
/// 密碼
/// </summary>
public string Password { get; set; }
}
並且修改 Login.razor
的內容
@page "/Login"
@using Blazor.Jwt.Shared
<div class="form-signin w-100 m-auto">
<EditForm Model="@loginDto" OnValidSubmit="HandleValidSubmit" data-bitwarden-watching="1">
<h1 class="h3 mb-3 fw-normal">請登入</h1>
<div class="form-floating">
<input type="email" class="form-control" id="floatingInput" placeholder="name@example.com"
@bind-value="loginDto.Username">
<label for="floatingInput">Email address</label>
</div>
<div class="form-floating">
<input type="password" class="form-control" id="floatingPassword" placeholder="Password"
@bind-value="loginDto.Password">
<label for="floatingPassword">Password</label>
</div>
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> 記住我
</label>
</div>
<button class="w-100 btn btn-lg btn-primary" type="submit">登入</button>
<p class="mt-5 mb-3 text-muted">© 2022</p>
</EditForm>
</div>
@code {
private LoginDto loginDto = new LoginDto();
private void HandleValidSubmit()
{
Console.WriteLine($"Username:{loginDto.Username}");
Console.WriteLine($"Password:{loginDto.Password}");
}
}
完成後可以試著填入資料並點選登入,如果沒意外的話可以有 Console 上看到,就代表成功將欄值綁定了
using
@using System.Net.Http
@inject HttpClient Http
在方法內呼叫 API
private async Task HandleValidSubmit()
{
var token = await(await Http.PostAsJsonAsync("api/Authorize/Login", loginDto)).Content.ReadAsStringAsync();
Console.WriteLine($"Token {token}");
}
做完前端後,要完成後端的部分不然是沒辦法作用的,在昨天的 API Controller 內加入一個新的 Action
[HttpPost]
public IActionResult Login(LoginDto query)
{
var key = "2022/09/28 IThome 鐵人賽";
var claims = new List<Claim>
{
// 使用者名稱
new(JwtRegisteredClaimNames.Sub,query.Username),
// Token Id
new(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString())
};
var claimsIdentity = new ClaimsIdentity(claims);
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
var tokenDescriptor = new SecurityTokenDescriptor
{
Issuer = "發行者",
Subject = claimsIdentity,
Expires = DateTime.UtcNow.AddMinutes(30),
SigningCredentials = signingCredentials
};
var tokenHandler = new JwtSecurityTokenHandler();
var securityToken = tokenHandler.CreateToken(tokenDescriptor);
return Ok(tokenHandler.WriteToken(securityToken));
}
完成後,建置完成後,到剛剛做的登入頁面,輸入帳號密碼登入!
做到這邊已經初步的打通了前後端,下一章會說明怎麼讓請求(Request)送出時帶著 Token,還有 Token 該如何保存才好